package com.usian.admin.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.usian.admin.config.RabbitMQConfig;
import com.usian.admin.feign.ArticleFeign;
import com.usian.admin.feign.WemediaFeign;
import com.usian.admin.mapper.AdChannelMapper;
import com.usian.admin.mapper.AdSensitiveMapper;
import com.usian.admin.service.WemediaNewsAutoScanService;
import com.usian.common.aliyun.GreeTextScan;
import com.usian.common.aliyun.GreenImageScanForUrl;
import com.usian.common.exception.CatchCustomException;
import com.usian.common.exception.code.AdminStatusCode;
import com.usian.common.exception.code.UserStatusCode;
import com.usian.model.admin.dtos.NewsAuthDto;
import com.usian.model.admin.pojos.AdChannel;
import com.usian.model.article.pojos.ApArticle;
import com.usian.model.article.pojos.ApArticleConfig;
import com.usian.model.article.pojos.ApArticleContent;
import com.usian.model.article.pojos.ApAuthor;
import com.usian.model.common.dtos.PageResponseResult;
import com.usian.model.common.dtos.ResponseResult;
import com.usian.model.common.enums.AppHttpCodeEnum;
import com.usian.model.media.pojos.WmNews;
import com.usian.model.media.pojos.WmUser;
import com.usian.model.media.vo.WmNewsVo;
import com.usian.user.common.SensitiveWordUtil;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.swing.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Service
@SuppressWarnings("ALL")
public class WemediaNewsAutoScanServiceImpl implements WemediaNewsAutoScanService {
    @Autowired
    private WemediaFeign wemediaFeign;
    @Autowired
    private AdChannelMapper adChannelMapper;
    @Autowired
    private GreeTextScan greeTextScan;
    @Autowired
    private GreenImageScanForUrl greenImageScanForUrl;
    @Autowired
    private AdSensitiveMapper adSensitiveMapper;
    @Autowired
    private ArticleFeign articleFeign;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 自媒体文章审核
     * @param id
     */
    @Override
    public void autoScanByMediaNewsId(Integer id) {
        //检查参数
        if (id == null) {
            CatchCustomException.catchs(AdminStatusCode
                    .PARAM_FAIL, "参数为空");
        }
        //2、根据id查询自媒体文章信息
        WmNews wmNews = wemediaFeign.findById(id);
        if (wmNews == null) {
            CatchCustomException.catchs(AdminStatusCode
                    .PARAM_FAIL, "需要审核对的文章没有找到");
        }
        //2、文章状态为4（人工那个审核通过）  直接保存数据和创建索引ES
        if (wmNews.getStatus() == 4) {
            //人工审核通过
            saveAppArticle(wmNews);//人工通过之后就执行成功了
            return;//直接结束此方法就可以
        }
        //3、文章状态为8   发布时间> 当前时间  直接保存数据  System.currentTimeMillis():当前时间
        if (wmNews.getStatus() == 8 && wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
            //人工审核通过
            saveAppArticle(wmNews);//执行保存文章的操作
            return;
        }
        //4、文章状态为1 待审核
        if (wmNews.getStatus() == 1) {
            //获取图文内容
            Map<String, Object> handleMap = handlleTextAndImages(wmNews);
            //4.1 进行文本发垃圾检测（阿里云）
            Boolean textBoolean = handleTextScan((List<String>) handleMap.get("contents"), wmNews);
//            if (!textBoolean) {
//                return;
//            }
            //4.2进行图片检查（阿里云）
           boolean imageBoolean= handleImagesScan((List<String>)handleMap.get("images"),wmNews);
//           if (!imageBoolean){
//               return;
//           }
            //4.3 进行敏感词查询（程序员自行维护）
            List<String> list = (List<String>) handleMap.get("content");
            StringBuilder sb = new StringBuilder();
            for (String s : list) {
                sb.append(s);
            }
            boolean sensitive = handleSensitive(sb.toString(), wmNews);
            if (!sensitive) {
                return;
            }
            //4.4  发布时间大于当前时间   代表审核通过  但是还没有到发布时间  状态为8  （定时发布）
            if (wmNews.getPublishTime() != null) {
                if (wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
                    updateWmNews(wmNews, (short) 8, "审核通过，待发布");
                    Message message = MessageBuilder
                            .withBody((wmNews.getId()+"").getBytes(StandardCharsets.UTF_8))//使用bytes流的方式实现
                            //必须使用 x-delay  key  定时
                            .setHeader("x-delay",wmNews.getPublishTime().getTime() - System.currentTimeMillis())
                             .build();
                    // 发送消息
                    rabbitTemplate.convertAndSend("authExchangedelay", "auth", message);
                    return;
                }
            }
        //5、审核通过  状态改为9  发布文章(article)
        saveAppArticle(wmNews);
    }
        if (wmNews.getStatus()==8 && wmNews.getPublishTime().getTime() < System.currentTimeMillis()){
            saveAppArticle(wmNews);
        }
}



    /**
     * 敏感词查询
     * @param content
     * @param wmNews
     * @return
     */
    private boolean handleSensitive(String content, WmNews wmNews) {
        boolean flag=true;
        //全部敏感词内容
        List<String> sensitive = adSensitiveMapper.findAllSensitive();
        //初始化FDA算法
        SensitiveWordUtil.initMap(sensitive);
        Map<String,Integer> maps=SensitiveWordUtil.matchWords(content);
        if (maps.size()>0){
            //记录日志
            //找到了敏感词，审核不通过
            updateWmNews(wmNews,(short)2,"文章中包含了敏感词");
            flag=false;
        }
        return flag;
    }

    /**
     * 阿里云  图片检测
     * @param images
     * @param wmNews
     * @return
     */
    private boolean handleImagesScan(List<String> images,WmNews wmNews){
        if (images == null){
            return true;
        }
        boolean flag=true;
        try{
            Map map=greenImageScanForUrl.imageScan(images);
            //审核不通过
            if (!map.get("suggestion").equals("pass")){
                //审核失败
                if (map.get("suggestion").equals("block")){
                    //修改自媒体文章的状态，并告知审核失败的原因  =2
                    updateWmNews(wmNews,(short)2,"文章中图片有违规");
                    flag=false;
                }
                //人工审核
                if (map.get("suggestion").equals("review")){
                    //修改自媒体文章的状态，并告知审核失败的原因  =2
                    updateWmNews(wmNews,(short)3,"文章中图片有违规");
                    flag=false;
                }
            }
        }catch (Exception e){
            flag=false;
        }
        return flag;
    }

    /**
     * 阿里云   文本检测
     * @param contennts
     * @param wmNews
     * @return
     */
    public Boolean handleTextScan(List<String> contennts, WmNews wmNews) {
        Boolean flag = true;
        try {
            Map map = greeTextScan.greeTextScan(contennts);
            //审核不通过
            if (!map.get("suggestion").equals("pass")) {
                //审核失败
                if (map.get("suggestion").equals("block")) {
                    //修改自媒体文章的状态，并告知审核失败的原因  =2
                    updateWmNews(wmNews, (short) 2, "文章内容中有敏感词汇");
                    flag = false;
                }
                //人工审核
                if (!map.get("suggestion").equals("review")) {
                    //修改自媒体文章状态，并告知失败原因  =3  需要人工
                    updateWmNews(wmNews,(short)3,"文章内容重有不确定词汇");
                    flag=false;
                }
            }
        } catch (Exception e) {
            flag=false;
        }
        return flag;
    }

    /**
     * 提取文本及图片
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> handlleTextAndImages(WmNews wmNews) {
        //文章内容
        String content = wmNews.getContent();
        //存储纯文本内容
        List<String> contents = new ArrayList<>();
        //存储图片
        List<String> images = new ArrayList<>();
        List<Map> contentList = JSONArray.parseArray(content, Map.class);
        //存缓文本内容
        for (Map map : contentList) {
            if (map.get("type").equals("text")) {
                contents. add((String)map.get("value"));
            }
            if (map.get("type").equals("image")) {
                images.add((String) map.get("value"));
            }
        }
//获取封面  防止0图情况
        if (wmNews.getImages() != null && wmNews.getType() != 0) {
            //如果有封面图片，将图片以，号分割
            String[] split = wmNews.getImages().split(",");
            images.addAll(Arrays.asList(split));
        }
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("content", contents);
        resultMap.put("images", images);
        return resultMap;
    }

    /**
     * 保存文章信息
     * 三件事：保存文章信息   保存文章配置  保存文章内容
     * @param wmNews   需要保存的自媒体文章信息
     */
    private void saveAppArticle(WmNews wmNews) {
        if (wmNews.getArticleId() == null){
            //1、保存文章信息
            ApArticle apArticle = this.saveArticle(wmNews);
            //保存文章配置
            saveArticleConfig(apArticle);
            //3、保存文章容
            saveArticleContent(apArticle, wmNews);
            //4、修改状态 ==9
            wmNews.setArticleId(apArticle.getId());
        }
        updateWmNews(wmNews, (short) 9, "审核成功");
        //同步索引库（以后实现）
    }

    /**
     * 保存app文章相关的数据
     *
     * @param wmNews
     */
    private ApArticle saveArticle(WmNews wmNews) {
        //获取数据  然后填充
        ApArticle apArticle = new ApArticle();
        apArticle.setChannelId(wmNews.getChannelId());//频道id
        apArticle.setTitle(wmNews.getTitle());//标题
        apArticle.setLayout(wmNews.getType());//0图  1 图  3图
        apArticle.setImages(wmNews.getImages());//封面
        apArticle.setCreatedTime(new Date());//创建时间
        apArticle.setLikes(0);//喜欢数  默认初始化为0
        apArticle.setCollection(0);//收藏数
        apArticle.setComment(0);//评论数
        apArticle.setViews(0);//阅读数
        apArticle.setLabels(wmNews.getLabels());//标签
        //获取频道名称
        Integer channelId = apArticle.getChannelId();
        AdChannel adChannel = adChannelMapper.selectById(channelId);//获取
        if (adChannel == null) {
            apArticle.setChannelName("");
        } else {
            apArticle.setChannelName(adChannel.getName());
        }
        //作者信息
        Integer wmUserId = wmNews.getUserId();
        //通过feign远程调用
        WmUser wmUser = wemediaFeign.findWmUserById(wmUserId);
        if (wmUser != null) {
            //获取作者名称
            String authorName = wmUser.getName();
            ApAuthor author= articleFeign.selectAuthorByName(authorName);
               if (author!=null){
                   apArticle.setAuthorId(Long.valueOf(author.getId()));
                   apArticle.setAuthorName(author.getName());
               }
            }

        return articleFeign.saveArticle(apArticle);
    }

    /**
     * 创建app端文章配置信息
     *
     * @param apArticle
     */
    private void saveArticleConfig(ApArticle apArticle) {
        ApArticleConfig apArticleConfig = new ApArticleConfig();
        apArticleConfig.setArticleId(apArticle.getId());
        //默认可以转发
        apArticleConfig.setIsForward(true);
        //默认不删除
        apArticleConfig.setIsDelete(false);
        //默认下架
        apArticleConfig.setIsDown(true);
        //默认可以评论
        apArticleConfig.setIsComment(true);
        articleFeign.saveArticleConfig(apArticleConfig);
    }

    /**
     * 创建app端文章内容信息
     * @param apArticle  文章信息
     * @param wmNews  自媒体文章信息
     */
    private void saveArticleContent(ApArticle apArticle, WmNews wmNews) {
        ApArticleContent apArticleContent = new ApArticleContent();
        apArticleContent.setArticleId(apArticle.getId());//文章id
        apArticleContent.setContent(wmNews.getContent());//文章内容
        articleFeign.saveArticleContent(apArticleContent);
    }

    /**
     * 修改文章状态    成功   失败 都调用他
     * @param wmNews 修改的状态
     * @param status 对应状态码
     * @param reason 成功  或  失败  的原因
     */
    private void updateWmNews(WmNews wmNews, Short status, String reason) {
        wmNews.setStatus(status);
        wmNews.setReason(reason);
        wemediaFeign.updateWmNews(wmNews);
    }

    /**
     * 根据文章标题分页查询自媒体文章列表
     * @param dto
     * @return
     */
    @Override
    public PageResponseResult findNews(NewsAuthDto dto) {
        //检查参数
        if (dto == null) {
            CatchCustomException.catchs(AdminStatusCode.PARAM_FAIL, "有问题");
        }
        //初始化分页
        dto.checkParam();
        //远程接口查询所有自媒体文章列表
        return wemediaFeign.findList(dto);
    }

    /**
     * 根据文章id文章信息
     * @param id
     * @return
     */
    @Override
    public ResponseResult findOne(Integer id) {
        //1参数检查
        if(id == null){
            CatchCustomException.catchs(AdminStatusCode.PARAM_FAIL, "有问题");
        }
        //2查询数据
        WmNewsVo wmNewsVo = wemediaFeign.findWmNewsVo(id);
        //结构封装
        ResponseResult responseResult = ResponseResult.okResult(wmNewsVo);
        return responseResult;
    }

    /**
     * 审核通过或驳回
     * @param type  0 为驳回  1位通过
     * @param dto
     * @return
     */
    @Override
    public ResponseResult updateStatus(Integer type, NewsAuthDto dto) {
        //1.参数检查
        if(dto == null || dto.getId() == null){
           CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"需要审核的文章没有找到");
        }
        //2.查询文章
        WmNews wmNews = wemediaFeign.findById(dto.getId());
        if(wmNews == null){
            CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"需要审核的文章没有找到");
        }
        //3.根据不同的状态进行修改
        if(type==0){
            updateWmNews(wmNews,(short)2,dto.getMsg());
        }else if(type==1){
            //4.人工审核通过
            updateWmNews(wmNews,(short)4,"人工审核通过");
        }else {
            CatchCustomException.catchs(UserStatusCode.PARAM_FAIL,"需要传递正确的审核id");
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }
}
